﻿using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Reflection;
using up6.sql;
using up6.sql.model;
using up6.utils;

namespace up6.db.sql
{
    public class SqlValueSeter
    {
        public static SqlValueSeter build() {
            var dbt = ConfigReader.dbType();
            if(dbt== DataBaseType.Oracle)
                return new OracleValueSeter();
            else if(dbt == DataBaseType.Kingbase)
                return new KingBaseValueSeter();
            return new SqlValueSeter();
        }

        public SqlValueSeter()
        {

        }

        /// <summary>
        /// 读取字段数据，并自动赋值到对象成员中，自动根据成员类型取值
        /// </summary>
        /// <param name="read"></param>
        /// <param name="fields"></param>
        /// <param name="model"></param>
        public virtual void read(DbDataReader read,string[] fields,object model)
        {
            Dictionary<string, bool> dic = new Dictionary<string, bool>();
            foreach (var f in fields) dic.Add(f.Trim(), true);

            int index = 0;
            foreach(var m in model.GetType().GetFields())
            {
                if(!m.IsDefined(typeof(DataBaseAttribute))) continue;
                var attr = (DataBaseAttribute)m.GetCustomAttribute(typeof(DataBaseAttribute));
                if(dic.ContainsKey(attr.name))
                {
                    if (m.FieldType == typeof(int)) m.SetValue(model, read.GetInt32(index));
                    else if (m.FieldType == typeof(short)) m.SetValue(model, read.GetInt16(index));
                    else if (m.FieldType == typeof(long)) m.SetValue(model, read.GetInt64(index));
                    else if (m.FieldType == typeof(string)) m.SetValue(model, read.GetString(index));
                    else if (m.FieldType == typeof(bool)) m.SetValue(model, read.GetBoolean(index));
                    else if (m.FieldType == typeof(DateTime)) m.SetValue(model, read.GetDateTime(index));
                    else if (m.FieldType == typeof(double)) m.SetValue(model, read.GetDouble(index));
                    else if (m.FieldType == typeof(float)) m.SetValue(model, read.GetDecimal(index));
                    index++;
                }
            }
        }

        /// <summary>
        /// 读取字段数据，并自动赋值到对象成员中，自动根据成员类型取值
        /// </summary>
        /// <param name="read"></param>
        /// <param name="fields"></param>
        /// <param name="model"></param>
        public virtual void read(DbDataReader read, SqlParam[] fields, object model)
        {
            //字段索引
            Dictionary<string,int> colIndex = new Dictionary<string,int>();
            Dictionary<string, bool> dic = new Dictionary<string, bool>();
            foreach (var f in fields)
            {
                dic.Add(f.Name, true);
                colIndex.Add(f.Name, colIndex.Count);
            }

            foreach (var m in model.GetType().GetFields())
            {
                if (!m.IsDefined(typeof(DataBaseAttribute))) continue;
                var attr = (DataBaseAttribute)m.GetCustomAttribute(typeof(DataBaseAttribute));
                if (dic.ContainsKey(attr.name))
                {
                    int index = colIndex[attr.name];//取索引
                    if (m.FieldType == typeof(int)) m.SetValue(model, read.IsDBNull(index) ? 0 : read.GetInt32(index));
                    else if (m.FieldType == typeof(short)) m.SetValue(model, read.IsDBNull(index) ? 0 : read.GetInt16(index));
                    else if (m.FieldType == typeof(long)) m.SetValue(model, read.IsDBNull(index) ? 0 : read.GetInt64(index));
                    else if (m.FieldType == typeof(string)) m.SetValue(model, read.IsDBNull(index) ? "" : read.GetString(index));
                    else if (m.FieldType == typeof(bool)) m.SetValue(model, read.IsDBNull(index) ? false: read.GetValue(index));
                    else if (m.FieldType == typeof(DateTime)) m.SetValue(model, read.IsDBNull(index) ? DateTime.Now:read.GetDateTime(index));
                    else if (m.FieldType == typeof(double)) m.SetValue(model, read.IsDBNull(index) ? 0:read.GetDouble(index));
                    else if (m.FieldType == typeof(float)) m.SetValue(model, read.IsDBNull(index) ? 0:read.GetDecimal(index));
                }
            }
        }
    }
}